using Ntreev.Library.Psd;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEngine;
using UnityEngine.UI;

public class PSD2UGUI : EditorWindow
{
    /// <summary>
    /// 资源路径
    /// </summary>
    private string res_path = "Assets/GameMain/UI/UISprites";
    string font_path = "Assets/GameMain/Fonts/MainFont.ttf";

    static Vector2 half_size = new Vector2(1334 * 0.5f, 750 * 0.5f);
    Dictionary<string, string> imgCacheDic = new Dictionary<string, string>();

    private Font font = default;
    string psd_path = string.Empty;

    private int imgIndex;
    private int groupIndex;
    private int textIndex;

    [MenuItem("Framework/PSD2UI")]
    private static void OpenWindow()
    {
        var window = CreateWindow<PSD2UGUI>();
        window.minSize = new Vector2(400, 180);
        window.maxSize = new Vector2(400, 180);
        window.maximized = false;
        window.titleContent = new GUIContent("PSD转UGUI");
    }

    private void OnEnable()
    {
        font = AssetDatabase.LoadAssetAtPath<Font>(font_path);
        string[] filePaths = Directory.GetFiles(res_path, "*.png", SearchOption.AllDirectories);

        foreach (var path in filePaths)
        {
            string fileName = Path.GetFileNameWithoutExtension(path);
            if (imgCacheDic.ContainsKey(fileName))
            {
                Debug.LogError("重名资源：" + path);
                continue;
            }
            imgCacheDic.Add(fileName, path);
        }
    }

    private void OnGUI()
    {
        GUILayout.BeginVertical("box");
        {
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("资源路径：", GUILayout.MaxWidth(80));
            EditorGUILayout.LabelField(res_path);

            if (GUILayout.Button("选择路径", GUILayout.MaxWidth(80)))
            {
                var path = EditorUtility.OpenFolderPanel("选择文件夹", string.Empty, string.Empty);
                if (!string.IsNullOrWhiteSpace(path))
                {
                    res_path = path;
                }
            }
            EditorGUILayout.EndHorizontal();
            EditorGUILayout.Space();
        }
        {
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("字体：", GUILayout.MaxWidth(80));
            font = EditorGUILayout.ObjectField(font, typeof(Font), false) as Font;
            EditorGUILayout.EndHorizontal();
            EditorGUILayout.Space();
        }
        {
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("psd路径：", GUILayout.MaxWidth(80));
            EditorGUILayout.LabelField(psd_path);

            if (GUILayout.Button("选择文件", GUILayout.MaxWidth(80)))
            {
                psd_path = EditorUtility.OpenFilePanel("选择文件", string.Empty, "psd");

            }
            EditorGUILayout.EndHorizontal();
            EditorGUILayout.Space();
        }

        if (GUILayout.Button("生成界面", GUILayout.MinHeight(60)))
        {
            imgIndex = 0;
            groupIndex = 0;
            textIndex = 0;
            GenUGUI();
        }
        GUILayout.EndVertical();
    }

    private void GenUGUI()
    {
        if (string.IsNullOrWhiteSpace(psd_path))
        {
            EditorUtility.DisplayDialog("错误", "psd路径为空", "确定");
            return;
        }
        if (string.IsNullOrWhiteSpace(res_path))
        {
            res_path = "Assets";
        }

        GameObject root = new GameObject("Panel", typeof(RectTransform));
        root.transform.SetParent(CheckCanvas()); SetRectTrans(root);
        PsdDocument psdDocument = PsdDocument.Create(psd_path);
        try
        {
            foreach (IPsdLayer doc in psdDocument.Childs)
            {
                CreateTran(root, root, doc);
            }
        }
        catch (System.Exception ex)
        {
            Debug.LogError(ex.Message);
        }
        finally
        {
            psdDocument.Dispose();
        }
        psdDocument.Dispose();
    }

    private void CreateTran(GameObject root, GameObject parent, IPsdLayer doc)
    {
        var obj = new GameObject("undefined", typeof(RectTransform));
        obj.transform.SetParent(parent.transform);

        if (doc.HasImage)
        {
            if (doc.Resources.Contains("TySh"))
            {
                CreateText(root, doc, obj);
            }
            else
            {
                CreateImage(root, doc, obj);
            }
        }
        else
        {
            if (doc.Name.StartsWith("btn_"))
            {
                CreateBtn(root, doc, obj);
                return;
            }
            else
            {
                obj.name = "Group_" + groupIndex;
                groupIndex++; SetRectTrans(obj);
            }
        }
        foreach (var item in doc.Childs)
        {
            CreateTran(root, obj, item);
        }
    }

    private void CreateBtn(GameObject root, IPsdLayer doc, GameObject obj)
    {
        var rectTransform = obj.GetComponent<RectTransform>();
        rectTransform.sizeDelta = new Vector2(doc.Width, doc.Height);
        rectTransform.anchoredPosition = new Vector2(doc.Left - half_size.x
            + doc.Width * 0.5f, half_size.y - doc.Top - doc.Height * 0.5f);

        obj.name = doc.Name; obj.tag = "Export";
        Button btn = obj.AddComponent<Button>();

        Image image = obj.AddComponent<Image>();
        btn.targetGraphic = image;
        string imgName = GetImageName(doc.Name);

        if (!imgCacheDic.ContainsKey(imgName))
        {
            Debug.LogError("资源：" + imgName + "，不存在！！！！");
        }
        else
        {
            image.sprite = AssetDatabase.LoadAssetAtPath<Sprite>(imgCacheDic[imgName]);
        }

        foreach (var item in doc.Childs)
        {
            if (item.Resources.Contains("TySh"))
            {
                GameObject textObj = new GameObject("undefined", typeof(RectTransform));
                textObj.transform.SetParent(obj.transform);
                CreateText(root, item, textObj);
            }
            else
            {
                GameObject imgObj = new GameObject("undefined", typeof(RectTransform));
                imgObj.transform.SetParent(obj.transform);
                CreateImage(root, item, imgObj);
            }
        }
    }

    private void CreateImage(GameObject root, IPsdLayer doc, GameObject obj)
    {
        var rectTransform = obj.GetComponent<RectTransform>();
        rectTransform.sizeDelta = new Vector2(doc.Width, doc.Height);
        rectTransform.anchoredPosition = new Vector2(doc.Left - half_size.x
            + doc.Width * 0.5f, half_size.y - doc.Top - doc.Height * 0.5f);

        obj.name = "Image_" + imgIndex; imgIndex++;
        Image image = obj.AddComponent<Image>();
        image.raycastTarget = false;

        string imgName = GetImageName(doc.Name);
        if (!imgCacheDic.ContainsKey(imgName))
        {
            Debug.LogError("资源：" + imgName + "，不存在！！！！");
        }
        else
        {
            image.sprite = AssetDatabase.LoadAssetAtPath<Sprite>(imgCacheDic[imgName]);
        }
    }

    private void CreateText(GameObject root, IPsdLayer doc, GameObject obj)
    {
        var rectTransform = obj.GetComponent<RectTransform>();
        Vector2 sizeDelta = new Vector2(doc.Width + 8, doc.Height + 8);
        rectTransform.sizeDelta = sizeDelta;
        rectTransform.anchoredPosition = new Vector2(doc.Left - half_size.x
            + sizeDelta.x * 0.5f, half_size.y - doc.Top - sizeDelta.y * 0.5f);

        obj.name = "Text_" + textIndex; textIndex++;
        Text text = obj.AddComponent<Text>();
        text.raycastTarget = false;
        if (font != null)
        {
            text.font = font;
        }

        IProperties prop = doc.Resources["TySh"] as IProperties;
        IProperties textProp = prop["Text"] as IProperties;
        text.text = textProp["Txt"].ToString();

        IProperties textStyle = GetTextStyle(textProp);
        float[] trans = prop["Transforms"] as float[];
        text.fontSize = Mathf.RoundToInt((float)textStyle["FontSize"] * trans[0]);

        IProperties fillColorProp = textStyle["FillColor"] as IProperties;
        float[] colorArray = (fillColorProp["Values"] as ArrayList).OfType<float>().ToArray();
        text.color = new Color(colorArray[1], colorArray[2], colorArray[3], colorArray[0]);

        if (doc.Resources.Contains("lfx2"))
        {
            //如果存在效果
            IProperties effectProp = doc.Resources["lfx2"] as IProperties;
            if (effectProp.Contains("FrFX"))
            {
                Outline line = obj.AddComponent<Outline>();
                IProperties outlineProp = effectProp["FrFX"] as IProperties;
                IProperties sizeProp = outlineProp["Sz"] as IProperties;
                float size = (float)sizeProp["Value"];
                line.effectDistance = new Vector2(Mathf.RoundToInt(size), Mathf.RoundToInt(size) * -1);

                Color32 color32 = new Color32();
                float a = (float)((outlineProp["Opct"] as IProperties)["Value"]);
                color32.a = (byte)(Mathf.RoundToInt(a) / 100f * 255f);

                IProperties colorProp = outlineProp["Clr"] as IProperties;
                color32.r = (byte)colorProp["Rd"];
                color32.g = (byte)colorProp["Grn"];
                color32.b = (byte)colorProp["Bl"];
                line.effectColor = color32;
            }
        }
    }

    private IProperties GetTextStyle(IProperties textProp)
    {
        IProperties tempPorp = textProp["EngineData"] as IProperties;
        tempPorp = tempPorp["EngineDict"] as IProperties;
        tempPorp = tempPorp["StyleRun"] as IProperties;

        ArrayList array = tempPorp["RunArray"] as ArrayList;
        tempPorp = array[0] as IProperties;
        tempPorp = tempPorp["StyleSheet"] as IProperties;
        return tempPorp["StyleSheetData"] as IProperties;
    }

    private string GetImageName(string orgName)
    {
        string[] strs = orgName.Split(new char[] { '*', '(', '（' },
            System.StringSplitOptions.RemoveEmptyEntries);
        if (strs.Length > 0)
        {
            return strs[0];
        }
        return "";
    }

    private void SetRectTrans(GameObject obj)
    {
        var rectTransform = obj.GetComponent<RectTransform>();
        rectTransform.anchorMin = Vector2.zero;
        rectTransform.anchorMax = Vector2.one;
        rectTransform.offsetMin = Vector3.zero;
        rectTransform.offsetMax = Vector3.zero;
    }

    /// <summary>
    /// 检查画布
    /// </summary>
    private Transform CheckCanvas()
    {
        Canvas root = FindObjectOfType<Canvas>();
        if (root == null)
        {
            var go = new GameObject("Canvas");
            root = go.AddComponent<Canvas>();
            root.renderMode = RenderMode.ScreenSpaceOverlay;
        }
        return root.transform;
    }
}